package com.lapelife.backend.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lapelife.backend.common.ErrorCode;
import com.lapelife.backend.common.RedisContains;
import com.lapelife.backend.common.ResponseResult;
import com.lapelife.backend.datasource.CSDNDataSourceImpl;
import com.lapelife.backend.datasource.DataSource;
import com.lapelife.backend.mapper.PostUserMapper;
import com.lapelife.backend.model.domain.LoginUser;
import com.lapelife.backend.model.domain.Post;
import com.lapelife.backend.model.domain.PostUser;
import com.lapelife.backend.model.domain.SysUser;
import com.lapelife.backend.model.request.PostRequest;
import com.lapelife.backend.service.PostService;
import com.lapelife.backend.mapper.PostMapper;
import com.lapelife.backend.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Mir.Lliao
 * @description 针对表【t_post(文章信息表)】的数据库操作Service实现
 * @createDate 2023-05-05 02:07:21
 */
@Service
public class PostServiceImpl extends ServiceImpl<PostMapper, Post>
        implements PostService {
    private PostMapper postMapper;

    private RedisUtil redisUtil;

    private PostUserMapper postUserMapper;

    @Autowired
    public void setPostUserMapper(PostUserMapper postUserMapper) {
        this.postUserMapper = postUserMapper;
    }

    @Autowired
    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    @Autowired
    public void setPostMapper(PostMapper postMapper) {
        this.postMapper = postMapper;
    }

    /**
     * 从CSDN爬取文章并添加到数据库
     *
     * @param postRequest：size（每个关键词查询到数据需要添加的数据量）、key（关键词数组）
     * @return 成功添加的数量
     */
    @Override
    @Transactional
    public ResponseResult<Integer> addPost(PostRequest postRequest) {
        String[] keys = postRequest.getKeys();
        Integer size = postRequest.getPostSize();
        if (keys == null || keys.length == 0) {
            return ResponseResult.fail(ErrorCode.PARAMS_ERROR);
        }
        size = size == null || size <= 0 || size > 1000 ? 10 : size;
        DataSource<Post> dataSource = new CSDNDataSourceImpl(redisUtil, this, postMapper);
        List<Post> post = dataSource.findPost(size, keys);
        if (post.size() == 0) {
            return ResponseResult.fail(ErrorCode.RESULT_ERROR);
        }
        Set<String> urlList = new HashSet<>();
        post.forEach(v -> urlList.add(v.getFromUrl()));
        // 从数据库获取相同url的文章
        List<String> dataUrlList = postMapper.selectFromUrlByFromUrlIn(urlList);

        // 比较爬取的文章的url与数据库的文章url
        List<Post> collect = post.stream().filter(v -> !dataUrlList.contains(v.getFromUrl())).collect(Collectors.toList());

        // 将文章添加到数据库
        // boolean b = saveBatch(collect);
        return ResponseResult.suc(collect.size());
    }

    @Override
    public ResponseResult<Integer> addPostByCustom(PostRequest postRequest) {
        if (!StringUtils.hasText(postRequest.getContent()) || !StringUtils.hasText(postRequest.getTitle())) {
            return ResponseResult.fail(ErrorCode.PARAMS_ERROR);
        }
        Post post = Convert.convert(Post.class, postRequest);
        post.setAuthor(getUser().getUserName());
        post.setFromUrl("");
        boolean b = save(post);
        if (b) {
            ResponseResult.fail(ErrorCode.RESULT_ERROR);
        }
        return ResponseResult.suc(1);
    }

    @Override
    public ResponseResult<Integer> updatePost(PostRequest postRequest) {
        if (postRequest.getPostId() == null) {
            return ResponseResult.fail(ErrorCode.PARAMS_ERROR);
        }
        Post post = Convert.convert(Post.class, postRequest);
        boolean b = updateById(post);
        if (b) {
            ResponseResult.fail(ErrorCode.RESULT_ERROR);
        }
        return ResponseResult.suc(1);
    }

    @Override
    @Transactional
    public ResponseResult<Integer> deletePost(Long... id) {
        if (id.length == 0) {
            return ResponseResult.fail(ErrorCode.PARAMS_ERROR);
        }
        boolean b = removeBatchByIds(Arrays.asList(id));
        if (b) {
            ResponseResult.fail(ErrorCode.RESULT_ERROR);
        }
        return ResponseResult.suc(id.length);
    }

    /**
     * 分页查询符合所有查询条件的文章
     *
     * @param postRequest：idList、title、content、author、tags
     * @return
     */
    @Override
    public ResponseResult<Page<Post>> queryPost(PostRequest postRequest) {
        if (postRequest.getIdList() != null && postRequest.getIdList().length != 0) {
            return queryPostById(postRequest);
        }
        Page<Post> page = new Page<>(postRequest.getCurrent(), postRequest.getSize());

        LambdaQueryWrapper<Post> wrapper = new LambdaQueryWrapper<>();
        String title = postRequest.getTitle();
        String content = postRequest.getContent();
        String author = postRequest.getAuthor();
        String tags = postRequest.getTags();

        if (StringUtils.hasText(title)) {
            wrapper.like(Post::getTitle, title);
        }
        if (StringUtils.hasText(content)) {
            wrapper.like(Post::getContent, content);
        }
        if (StringUtils.hasText(author)) {
            wrapper.like(Post::getAuthor, author);
        }
        if (StringUtils.hasText(tags)) {
            wrapper.like(Post::getTags, tags);
        }
        return ResponseResult.suc(page(page, wrapper));
    }

    /**
     * 通过id列表分页查询文章
     *
     * @param postRequest：idList
     * @return
     */
    @Override
    public ResponseResult<Page<Post>> queryPostById(PostRequest postRequest) {
        Page<Post> page = new Page<>(postRequest.getCurrent(), postRequest.getSize());

        Long[] id = postRequest.getIdList();
        // id不为null，通过id查询文章
        if (id == null || id.length == 0) {
            return ResponseResult.fail(ErrorCode.PARAMS_ERROR);
        }

        LambdaQueryWrapper<Post> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Post::getPostId, Arrays.asList(postRequest.getIdList()));

        return ResponseResult.suc(page(page, wrapper));
    }

    /**
     * 分页查询符合任意条件的文章
     *
     * @param postRequest：title、content、author、tags
     * @return
     */
    @Override
    public ResponseResult<Page<Post>> queryPostByKey(PostRequest postRequest) {
        postRequest.patternEmpty();
        String key = postRequest.getKey();
        Page<Post> page = new Page<>(postRequest.getCurrent(), postRequest.getSize());

        LambdaQueryWrapper<Post> wrapper;

        LambdaQueryWrapper<PostUser> postUserLambdaQueryWrapper = null;

        Page<Post> postPage;

        Set<Long> idSet = new HashSet<>();



        if (StringUtils.hasText(key)) {
            wrapper = new LambdaQueryWrapper<>();

            wrapper.and(v -> v.like(Post::getTitle, key)
                    .or()
                    .like(Post::getContent, key)
                    .or()
                    .like(Post::getAuthor, key)
                    .or()
                    .like(Post::getTags, key));

        } else {
            wrapper = new LambdaQueryWrapper<>();
            String title = postRequest.getTitle();
            String content = postRequest.getContent();
            String author = postRequest.getAuthor();
            String tags = postRequest.getTags();
            wrapper.and(false, v -> {
                if (StringUtils.hasText(title)) {
                    v.like(Post::getTitle, title).or();
                }
                if (StringUtils.hasText(content)) {
                    v.like(Post::getContent, content).or();
                }
                if (StringUtils.hasText(author)) {
                    v.like(Post::getAuthor, author).or();
                }
                if (StringUtils.hasText(tags)) {
                    v.like(Post::getTags, tags);
                }
            });
        }

        if (postRequest.getCollectTag().equals("1")) {
            Set keys = redisUtil.keys(RedisContains.POST_COLLECT + "*");
            keys.forEach(value -> {
                String v = (String) value;
                Long id = Convert.convert(Long.class, v.replace(RedisContains.POST_COLLECT, ""));
                if (redisUtil.sHasKey(v, getUser().getUserId())) {
                    idSet.add(id);
                }
            });
            if (idSet.size() == 0) {
                page.setTotal(0);
                return ResponseResult.suc(page);
            }
            wrapper.eq(Post::getStatus, "0");
            wrapper.and(v -> v.in(Post::getPostId, idSet));
            postPage = page(page, wrapper);
            postPage.setTotal(idSet.size());
        }else if (postRequest.getLookTag().equals("1")) {
            postUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
            postUserLambdaQueryWrapper.select(PostUser::getPostId).eq(PostUser::getUserId, getUser().getUserId()).orderByDesc(PostUser::getLookTime);
            Page<PostUser> postUserPage = postUserMapper.selectPage(new Page<>(postRequest.getCurrent(), postRequest.getSize()), postUserLambdaQueryWrapper);
            List<Long> idList = new ArrayList<>();
            if(postUserPage.getRecords().size() == 0){
                page.setTotal(0);
                return ResponseResult.suc(page);
            }
            for (PostUser v : postUserPage.getRecords()) {
                idList.add(v.getPostId());
            }
            wrapper.eq(Post::getStatus, "0");
            wrapper.and(v -> v.in(Post::getPostId, idList));
            postPage = page(page, wrapper);
            postPage.setTotal(postUserPage.getTotal());
        }else {
            postPage = page(page, wrapper);

        }

        return ResponseResult.suc(postPage);
    }

    private SysUser getUser() {
        // 获取用户信息
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return loginUser.getSysUser();
    }
}




